﻿using System;
using System.Diagnostics;
using System.Globalization;

namespace StoCombatLogHUD.Parsing
{
	/// <summary>
	/// Represents a single combatlog entry.
	/// </summary>
	public class CombatLogEntry
	{
		/// <summary>
		/// Possible Flags.
		/// </summary>
		[Flags]
		public enum CombatFlags
		{
			Any = 1,
			Miss = 2,
			Immune = 4,
			Critical = 8,
			Kill = 16
		}

		/// <summary>
		/// Gets or sets the timestamp.
		/// </summary>
		/// <value>
		/// The timestamp.
		/// </value>
		public DateTime Timestamp { get; set; }

		/// <summary>
		/// Gets or sets the owner.
		/// </summary>
		/// <value>
		/// The owner.
		/// </value>
		public CombatLogNameEntry Owner { get; set; }

		/// <summary>
		/// Gets or sets the source.
		/// </summary>
		/// <value>
		/// The source.
		/// </value>
		public CombatLogNameEntry Source { get; set; }

		/// <summary>
		/// Gets or sets the target.
		/// </summary>
		/// <value>
		/// The target.
		/// </value>
		public CombatLogNameEntry Target { get; set; }

		/// <summary>
		/// Gets or sets the event.
		/// </summary>
		/// <value>
		/// The event.
		/// </value>
		public CombatLogNameEntry Event { get; set; }

		/// <summary>
		/// Gets or sets the type.
		/// </summary>
		/// <value>
		/// The type.
		/// </value>
		public string Type { get; set; }

		/// <summary>
		/// Gets or sets the flags.
		/// </summary>
		/// <value>
		/// The flags.
		/// </value>
		public CombatFlags Flags { get; set; }

		/// <summary>
		/// Gets or sets the magnitute.
		/// </summary>
		/// <value>
		/// The magnitute.
		/// </value>
		public double Magnitute { get; set; }

		/// <summary>
		/// Gets or sets the base magnitude.
		/// </summary>
		/// <value>
		/// The base magnitude.
		/// </value>
		public double BaseMagnitude { get; set; }

		/// <summary>
		/// The time stamp format used for combatlog entries
		/// </summary>
		private const string TimeStampFormat = "yy:MM:dd:HH:mm:ss.f";

		/// <summary>
		/// Returns a <see cref="System.String" /> that represents this instance.
		/// </summary>
		/// <returns>
		/// A <see cref="System.String" /> that represents this instance.
		/// </returns>
		public override string ToString()
		{
			return
				Timestamp.ToString(TimeStampFormat, CultureInfo.InvariantCulture) + "::" +
				Owner.DisplayName + "," +
				Owner.InternalName + "," +
				Source.DisplayName + "," +
				Source.InternalName + "," +
				Target.DisplayName + "," +
				Target.InternalName + "," +
				Event.DisplayName + "," +
				Event.InternalName + "," +
				Type + "," +
				((Flags != CombatFlags.Any)
					 ? Flags.ToString().Replace(", ", "|")
					 : string.Empty) + "," +
				Magnitute.ToString(CultureInfo.InvariantCulture) + "," +
				BaseMagnitude.ToString(CultureInfo.InvariantCulture);
		}

		/// <summary>
		/// Creates a <see cref="CombatLogEntry"/> by parsing a given string.
		/// </summary>
		/// <param name="str">The string.</param>
		/// <returns></returns>
		public static CombatLogEntry FromString(string str)
		{
			var values = str.Split(new[] {"::", ","}, StringSplitOptions.None);
			if (values.Length != 13)
				throw new FormatException();

			CombatFlags flags;
			if (!Enum.TryParse(values[10].Replace('|', ','), out flags))
				flags = CombatFlags.Any;

			return new CombatLogEntry
				{
					Timestamp = DateTime.ParseExact(values[0], TimeStampFormat, CultureInfo.InvariantCulture),
					Owner = new CombatLogNameEntry {DisplayName = values[1], InternalName = values[2]},
					Source = new CombatLogNameEntry {DisplayName = values[3], InternalName = values[4]},
					Target = new CombatLogNameEntry {DisplayName = values[5], InternalName = values[6]},
					Event = new CombatLogNameEntry {DisplayName = values[7], InternalName = values[8]},
					Type = values[9],
					Flags = flags,
					Magnitute = double.Parse(values[11], CultureInfo.InvariantCulture),
					BaseMagnitude = double.Parse(values[12], CultureInfo.InvariantCulture)
				};
		}
	}
}
